package com.situ.skymallgateway.config;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.situ.skymallgateway.config.AuthInfo;
import com.situ.skymallgateway.config.GatewayAuthConfig;
import com.situ.utils.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.List;

@Component
public class JwtGlobalFilter implements GlobalFilter, Ordered {

    // private static final Logger log = LoggerFactory.getLogger(JwtGlobalFilter.class);  // 删除这行
    private final AntPathMatcher pathMatcher = new AntPathMatcher();

    @Value("${jwt.secret}")
    private String jwtSecret;

    @Autowired
    private GatewayAuthConfig gatewayAuthConfig;

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getURI().getPath();

        System.out.println("处理请求路径: " + path); // 替换为System.out

        // 1. 白名单检查：如果请求路径匹配白名单，则直接放行
        List<String> whitelist = gatewayAuthConfig.getWhitelist();
        for (String pattern : whitelist) {
            if (pathMatcher.match(pattern, path)) {
                System.out.println("请求命中白名单，直接放行: " + path); // 替换为System.out
                return chain.filter(exchange);
            }
        }

        // 2. 从请求头中提取Token
        String authHeader = request.getHeaders().getFirst("Authorization");
        String jwt = null;
        if (StringUtils.hasText(authHeader)) {
            if (authHeader.startsWith("Bearer ")) {
                // 如果有Bearer前缀，去掉前缀
                jwt = authHeader.substring(7);
            } else {
                // 如果没有Bearer前缀，直接使用整个Authorization头作为JWT
                jwt = authHeader;
            }
        }

        if (!StringUtils.hasText(jwt)) {
            return sendError(exchange.getResponse(), "未提供Token，禁止访问");
        }

        // 3. 统一验证JWT，并智能处理多角色
        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(jwtSecret)).build();
            DecodedJWT dj = verifier.verify(jwt);

            //[关键] 提取公共信息和角色(scope)信息
            String id = dj.getClaim("id").asString();
            String name = dj.getClaim("name").asString();
            String scope = dj.getClaim("scope").asString();

            if (!StringUtils.hasText(scope)) {
                return sendError(exchange.getResponse(), "Token无效：缺少'scope'角色声明");
            }

            // 4. 构建统一的AuthInfo对象
            AuthInfo authInfo = new AuthInfo(id, name, scope);
            // 如果是Admin角色，额外提取isSuper信息
            if ("ADMIN".equals(scope)) {
                authInfo.setIsSuper(dj.getClaim("isSuper").asInt());
            }

            // 5. 将AuthInfo对象序列化为JSON，再通过Base64编码后放入新的请求头
            String authInfoJson = objectMapper.writeValueAsString(authInfo);
            String encodedAuthInfo = Base64.getEncoder().encodeToString(authInfoJson.getBytes(StandardCharsets.UTF_8));

            // 构建ServerWebExchange（通过 mutate 链式修改请求头）
            ServerWebExchange ex = exchange.mutate()
                    .request(b -> b.header("x-auth-info", encodedAuthInfo))
                    .build();

            System.out.println("JWT验证通过, 角色: " + scope + ", ID: " + authInfo.getId());
            // 6. 放行（使用ServerWebExchange）
            return chain.filter(ex);

        } catch (Exception e) {
            System.err.println("JWT处理或验证异常: " + e.getMessage());
            return sendError(exchange.getResponse(), "Token无效或已过期");
        }
    }

    @Override
    public int getOrder() {
        return -100; // 确保此过滤器有较高的优先级
    }

    private Mono<Void> sendError(ServerHttpResponse response, String msg) {
        response.setStatusCode(HttpStatus.UNAUTHORIZED);
        response.getHeaders().add("Content-Type", "application/json;charset=utf-8");
        try {
            String json = objectMapper.writeValueAsString(JsonResult.fail(HttpStatus.UNAUTHORIZED.value(), msg));
            DataBuffer buffer = response.bufferFactory().wrap(json.getBytes(StandardCharsets.UTF_8));
            return response.writeWith(Mono.just(buffer));
        } catch (Exception e) {
            return Mono.error(e);
        }
    }
}
